import sys
import asyncio
from PyQt5.QtCore import QThread, pyqtSignal
from MyTT import EMA
import numpy as np
import pandas as pd
from tqsdk import TqApi
from db_manager import connect_db, get_monitored_products
import time 
from tqsdk import TqApi, TqAuth, TqAccount, TqSim,TqKq

class AsyncOpenCloseStrategy(QThread):
    def __init__(self, symbols, lots):
        # 调用父类的初始化方法
        super().__init__()
        #快期模拟账户
        tq_kq = TqKq()
        self.api = TqApi(account=tq_kq, auth=TqAuth("cps168", "alibaba999"))
        self.symbols = symbols
        self.lots = lots
        self.running = False
        self.main_task = None
        self.active_symbols = set()  # 新增运行状态跟踪
        self.loop = asyncio.new_event_loop()
        #self.loop = loop or asyncio.new_event_loop()  # 使用传入的loop或新建

    #线程启动时执行，线程启动后会启动调用run方法，在这里重写run方法
    # def run(self):
    #     print("************************已启动策略************************")
    #     self.running = True
    #     if self.main_task:
    #         self.main_task.cancel()

    #     asyncio.set_event_loop(self.loop)        
    #     try:
    #         self.loop.run_until_complete(self._run_all_symbols())
    #     except Exception as e:
    #         #print(f"错误: {str(e)}")
    #         pass
    #     finally:
    #         self.loop.close()

    #     return self.main_task

    def run(self):
        print("************************已启动策略************************")
        self.running = True
        if self.main_task:
            self.main_task.cancel()

        # 确保使用与TqApi相同的事件循环
        self.loop = asyncio.get_event_loop()
        asyncio.set_event_loop(self.loop)            
        try:
            self.loop.run_until_complete(self._run_all_symbols())
        except Exception as e:
            print(f"错误: {str(e)}")
            pass
        finally:
            self.loop.close()

        return self.main_task

    async def _run_all_symbols(self):
        """并行处理所有品种"""
        print(f"开始处理品种列表: {self.symbols}")
        # 使用当前循环创建任务
        tasks = [asyncio.create_task(self._process_product(symbol)) for symbol in self.symbols]
        await asyncio.gather(*tasks)

    async def _process_product(self, symbol):
        """单个品种处理协程"""
        self.active_symbols.add(symbol)
        #print(f"{time.strftime('%X')} 策略开始运行。。。")  # 修正时间格式
        try:  
            while True:
                print(f"{time.strftime('%X')} {symbol} 正在运行...")  # 修正时间格式
                quote = self.api.get_quote(symbol)  # 移出async with块        
                klines = self.api.get_kline_serial(symbol, 5*60, 500)        
                #等待行情更新
                async with self.api.register_update_notify() as update_chan:
                    async for _ in update_chan:
                        if not self.running:  # 添加停止检查
                            return
                        print("行情已更新。。。！")
                        if self.api.is_changing(quote):
                            print(f"{time.strftime('%X')} K线已变化,{symbol} 价格是：{quote.last_price}")
                            q = (3*klines.close + klines.low + klines.open + klines.high) / 6
                            ma_values = self._calculate_ma(q)
                            short_ma = ma_values['ma']
                            ema_7 = ma_values['ema']
                            
                            position = self.api.get_position(symbol)
                            
                            # 平空仓逻辑
                            if short_ma[-2] > ema_7[-2]:  
                                if position.pos_short > 0:
                                    self.api.insert_order(symbol, direction="BUY", offset="CLOSE", 
                                                    volume=position.pos_short)
                            # 开多仓逻辑
                            if position.pos_long == 0 and position.pos_short == 0 and short_ma[-3] < ema_7[-3] and short_ma[-2] > ema_7[-2]:
                                self.api.insert_order(symbol, direction="BUY", offset="OPEN", 
                                                volume=self.lots)
                                
                            # 平多仓逻辑
                            if short_ma[-2] < ema_7[-2]:  
                                if position.pos_long > 0:
                                    self.api.insert_order(symbol, direction="SELL", offset="CLOSE", 
                                                    volume=position.pos_long)
                            # 开空仓逻辑
                            if position.pos_long == 0 and position.pos_short == 0 and short_ma[-3] > ema_7[-3] and short_ma[-2] < ema_7[-2]:
                                self.api.insert_order(symbol, direction="SELL", offset="OPEN", 
                                                volume=self.lots)
                        print("************************策略运行结束************************")
        except Exception as e:
            print(f"Error processing symbol {symbol}: {e}")                        
        finally:
            self.active_symbols.remove(symbol)

    # def _calculate_ma(self, q):
    #     """自定义权重计算（与原版完全一致）"""
    #     weights = np.arange(26, 0, -1)
    #     ma = []
    #     q_array = np.array(q)
    #     for i in range(len(q_array)):
    #         if i < 26:
    #             ma.append(np.nan)
    #             continue
    #         window = q_array[i-26:i+1]
    #         ma.append(np.dot(window, weights) / 351)
        
    #     ema_7 = EMA(pd.Series(ma), 7)
    #     return {'ma': ma, 'ema': ema_7.tolist()}

    def _calculate_ma(self, q):
        """自定义权重计算（与原版完全一致）"""
        weights = np.arange(26, 0, -1)
        ma = []
        q_array = np.array(q)
        for i in range(len(q_array)):
            if i < 25:  # 修改为25，因为窗口大小现在是26
                ma.append(np.nan)
                continue
            window = q_array[i-25:i+1]  # 修改为i-25，这样窗口大小就是26
            ma.append(np.dot(window, weights) / 351)
        
        ema_7 = EMA(pd.Series(ma), 7)
        return {'ma': ma, 'ema': ema_7.tolist()}

    async def stop(self):
        """停止策略"""
        self.running = False
        if self.main_task:
            await self.main_task
            self.main_task = None